package com.coolxiaoyao.web.converter;

import com.coolxiaoyao.common.annotation.PathVariable;
import com.coolxiaoyao.common.annotation.RequestBody;
import com.coolxiaoyao.common.annotation.RequestParam;
import com.coolxiaoyao.common.exception.HttpBadRequestException;
import com.coolxiaoyao.common.inner.UrlInnerExchange;
import com.coolxiaoyao.common.util.ClassUtil;
import com.coolxiaoyao.common.util.StringUtils;
import com.coolxiaoyao.web.util.SerializationUtil;
import io.netty.handler.codec.http.QueryStringDecoder;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Kerry on 18/09/20
 */

public class ObjectConverter {

    /**
     * URL参数数组分割符
     */
    private static final String PATTERN_SPLIT_REG = ",";


    @SuppressWarnings("AlibabaMethodTooLong")
    @NotNull
    public Object[] getObjectParams(Class<?>[] paramTypes, Annotation[][] parameterAnnotations, QueryStringDecoder params, byte[] steam, UrlInnerExchange exchange) throws IOException {
        // 默认值
        Object[] defaultArgs = ClassUtil.getObjectArrayDefaultValue(paramTypes);
        // URL Query 参数
        Map<String, List<String>> urlQueryParameters = params.parameters();

        int pathIndex = 0;
        for (int i = 0; i < paramTypes.length; i++) {
            Class<?> paramType = paramTypes[i];
            for (int j = 0; j < parameterAnnotations[i].length; j++) {
                Annotation annotation = parameterAnnotations[i][j];
                if (annotation instanceof PathVariable) {
                    pathIndex++;
                    //未处理
                    // TODO FIX
                    Pattern compile = Pattern.compile(exchange.getPatternStr());
                    Matcher matcher = compile.matcher(exchange.getSourceUrl());

                    while (matcher.find()) {
                        defaultArgs[i] = ClassUtil.convertValueByClass(paramType, matcher.group(pathIndex));
                    }
                } else if (annotation instanceof RequestParam) {
                    RequestParam requestParam = (RequestParam) annotation;
                    List<String> list = urlQueryParameters.get(requestParam.value());
                    if (list == null || list.isEmpty()) {
                        if (requestParam.required()) {
                            if (StringUtils.isBlank(requestParam.defaultValue())) {
                                throw new HttpBadRequestException(params.toString());
                            }
                        }
                        defaultArgs[i] = ClassUtil.convertValueByClass(paramType, requestParam.defaultValue());
                    } else {
                        if (paramType.isArray()) {

                            // TODO only one item
                            String ps = list.get(0);
                            String[] split = ps.split(PATTERN_SPLIT_REG);


                            //paramType.getComponentType() String[] 取得 String.class 类型
                            Object subArray = Array.newInstance(paramType.getComponentType(), split.length);
                            for (int x = 0; x < split.length; x++) {
                                Array.set(subArray, x, ClassUtil.convertValueByClass(paramType.getComponentType(), split[x]));
                            }
                            defaultArgs[i] = subArray;
                            defaultArgs[i] = subArray;
                        } else if (List.class.isAssignableFrom(paramType)) {

                            // TODO only one item
                            String ps = list.get(0);
                            String[] split = ps.split(PATTERN_SPLIT_REG);

                            // TODO 泛型问题,这里只支持了 List<String>

                            List<String> subList = new ArrayList<>(split.length);

                            for (String aSplit : split) {
                                subList.add(aSplit.trim());
                            }
                            defaultArgs[i] = subList;
                        } else {
                            defaultArgs[i] = ClassUtil.convertValueByClass(paramType, list.get(0));
                        }
                    }
                } else if (annotation instanceof RequestBody) {
                    if (paramType == String.class) {
                        defaultArgs[i] = new String(steam, Charset.defaultCharset());
                    } else {
                        try {
                            defaultArgs[i] = SerializationUtil.fromJson(steam, paramType);
                        } catch (IOException e) {
                            if (((RequestBody) annotation).required()) {
                                throw e;
                            } else {
                                defaultArgs[i] = ClassUtil.getObjectDefaultValue(paramType);
                            }
                        }

                    }
                }
            }
        }

        return defaultArgs;
    }


}
